const {
	Service
} = require('uni-cloud-router')
const uniID = require('uni-id')

const dbHelper = require('db-helper')
const {
	wxPubConfig
} = require("config");
const WxPubApi = require("wx-public-api")
const wxPubApi = new WxPubApi()
const moment = require('moment-timezone');

module.exports = class UserService extends Service {

	async addUser({
		nickname,
		username,
		password,
		role,
		mobile,
		status,
		merchant_info,
		city
	}) {
		let result
		try {
			let data = {
				nickname,
				username,
				password,
				role,
				mobile,
				status
			}
			let isShareDM = role.some(item => {
				return item == 'share_DM'
			})
			if (isShareDM) {
				data.compereStatus = {
					status: 0
				}
			}
			result = await uniID.register(data)
			delete result.token
			delete result.tokenExpired
		} catch (e) {
			throw e
		}
		// console.log('register', result)

		if (result.code) {
			throw new Error(result.msg)
		}

		let transaction = await this.db.startTransaction()
		try {
			let userId
			let sysConfig = await dbHelper.getOne("t3ds-system-config", {
				key: 'userNo'
			})
			if (!sysConfig) {
				await dbHelper.insert("t3ds-system-config", {
					"key": "userNo",
					"value": 1
				}, transaction)
				userId = 1
			} else {
				userId = sysConfig.value + 1
				await transaction.collection("t3ds-system-config").doc(sysConfig._id)
					.update({
						value: userId
					})
			}
			await transaction.collection("uni-id-users").doc(result.uid)
				.update({
					id: userId,
					city,
					merchant_info
				})

			// 创建现金账户
			let count = await dbHelper.getCount("t3ds-account", {
				userId: result.uid
			})
			if (!count) {
				await dbHelper.insert("t3ds-account", {
					userId: result.uid,
					total: 0,
					balance: 0,
					settle: 0,
					frozen: 0,
					createTime: Date.now(),
					createBy: 'admin'
				}, transaction)
			}
			await transaction.commit()
			let user = await dbHelper.getById("uni-id-users", result.uid)
			return user
		} catch (e) {
			await transaction.rollback()
			this.db.collection("uni-id-users").doc(result.uid).remove()
			throw e
		}
	}

	async getMemberList({
		keyword,
		pageNum = 1,
		pageSize = 10
	}) {
		let query = {
			role: 'member',
			id: this.db.command.exists(true)
		}
		if (keyword) {
			if (/^1(3|4|5|6|7|8|9)\d{9}$/.test(keyword)) {
				query.mobile = keyword
			} else if (/\d+/.test(keyword)) {
				query.id = parseInt(keyword)
			} else {
				query.nickname = new RegExp(keyword)
			}
		}
		let result = {
			total: 0,
			list: []
		}
		if (pageNum == 1) {
			let countRes = await this.db.collection("uni-id-users")
				.where(query)
				.count()
			if (!countRes.total) {
				return result
			}
			result.total = countRes.total
		}
		let res = await this.db.collection("uni-id-users")
			.where(query)
			.orderBy("register_date", "desc")
			.field({
				token: false
			})
			.skip((pageNum - 1) * pageSize)
			.limit(pageSize)
			.get()
		result.list = res.data
		return result
	}

	async getShareExpertList({
		keyword,
		isShare,
		city,
		pageNum = 1,
		pageSize = 10
	}) {
		let dbCmd = this.db.command
		let query = {
			role: 'member',
			id: this.db.command.exists(true)
		}
		if (isShare != null) {
			query.shareGrade = dbCmd.gt(0)
		}
		if (city) {
			query.city = city
		}
		if (keyword) {
			if (/^1(3|4|5|6|7|8|9)\d{9}$/.test(keyword)) {
				query.mobile = keyword
			} else if (/\d+/.test(keyword)) {
				query.id = parseInt(keyword)
			} else {
				query.nickname = new RegExp(keyword)
			}
		}
		let result = {
			total: 0,
			list: []
		}
		if (pageNum == 1) {
			let countRes = await this.db.collection("uni-id-users")
				.where(query)
				.count()
			if (!countRes.total) {
				return result
			}
			result.total = countRes.total
		}
		let res = await this.db.collection("uni-id-users")
			.where(query)
			.orderBy("register_date", "desc")
			.field({
				token: false
			})
			.skip((pageNum - 1) * pageSize)
			.limit(pageSize)
			.get()
		result.list = res.data
		return result
	}

	async getUserList({
		keyword,
		role,
		city,
		pageNum = 1,
		pageSize = 10
	}) {
		let dbCmd = this.db.command
		var query = []
		if (role) {
			if (role == 'employee' || role == 'employee_2' || role === 'logistics') {
				query.push({
          role: dbCmd.or(dbCmd.eq('employee'), dbCmd.eq('employee_2'), dbCmd.eq('logistics'))
				})
			} else {
				query.push({
					role
				})
			}
		} else {
			query.push({
				role: dbCmd.neq('admin').and(dbCmd.neq('member'))
			})
		}
		if (keyword) {
			query.push(
				dbCmd.or({
					mobile: new RegExp(keyword)
				}, {
					id: parseInt(keyword)
				}, {
					nickname: new RegExp(keyword)
				}, {
					username: new RegExp(keyword)
				}, {
					merchant_info: {
						name: new RegExp(keyword)
					}
				}))
		}
		if (city) {
			query.push({
				city
			})
		}
		// query.push({
		// 	_id: dbCmd.neq(this.ctx.auth.uid)
		// })
		query = dbCmd.and(query)
		//console.log('query', query)
		let result = {
			total: 0,
			list: []
		}
		if (pageNum == 1) {
			let countRes = await this.db.collection("uni-id-users")
				.where(query)
				.count()
			if (!countRes.total) {
				return result
			}
			result.total = countRes.total
		}

		let res = await this.db.collection("uni-id-users")
			.where(query)
			.orderBy("register_date", "desc")
			.field({
				token: false
			})
			.skip((pageNum - 1) * pageSize)
			.limit(pageSize)
			.get()
		result.list = res.data
		return result
	}

	async getUserStatistics({
		userId
	}) {
		let dbCmd = this.db.command
		let $ = dbCmd.aggregate
		try {
			let user = await dbHelper.getById("uni-id-users", userId);
			if (!user) {
				throw new Error("用户不存在")
			}
			let account = await dbHelper.getOne("t3ds-account", {
				userId: userId
			})
			let stores = await dbHelper.getList("t3ds-store", {
				uid: user._id
			})
			// 门店数
			let storeCount = stores.length;

			// 核销记录数
			let storeIds = stores.map(item => {
				return item._id;
			})
			let orderCount = await dbHelper.getCount("t3ds-ticket-code", {
				storeId: dbCmd.in(storeIds),
				status: 1
			})

			// 已提现
			let withdrawRes = await this.db.collection("t3ds-withdraw-apply").aggregate()
				.match({
					userId: userId,
					status: 'PASSED'
				})
				.group({
					_id: null,
					total: $.sum("$fee")
				})
				.end()
			var withdraw = 0;
			if (withdrawRes.data && withdrawRes.data.length) {
				withdraw = withdrawRes.data[0].total;
			}

			return {
				userInfo: user,
				account,
				storeCount,
				orderCount,
				withdraw
			}
		} catch (e) {
			uniCloud.logger.error("查询用户详情遇到错误", e);
			throw e
		}
	}

	async getUserInfoById({
		id,
		_id
	}) {
		if (id) {
			let user = await dbHelper.getOne("uni-id-users", {
				id: parseInt(id)
			})
			if (user) {
				return {
					_id: user._id,
					id: user.id,
					nickname: user.nickname,
					avatar: user.avatar,
					shareGrade: user.shareGrade
				}
			}
		} else if (_id) {
			let user = dbHelper.getById("uni-id-users", _id)
			if (user) {
				return {
					_id: user._id,
					id: user.id,
					nickname: user.nickname,
					avatar: user.avatar,
					shareGrade: user.shareGrade
				}
			}
		}
	}

	async login({
		username,
		password
	}) {
		const res = await uniID.login({
			username,
			password,
			needPermission: true
		})
		console.log('UserService::login', res)
		if (res.code) {
			return res
		}
		await this.checkToken(res.token, {
			needPermission: true,
			needUserInfo: false
		})
		res.userInfo.permission = this.ctx.auth.permission
		if (this.ctx.auth.role.includes('admin')) {
			return res
		}
		return res
		// 暂时放开菜单判断，无菜单也可以登陆
		// const navMenu = await this.service.menu.getMenu()
		// if (navMenu.length) {
		// 	return res
		// }
		// return {
		// 	code: 10001,
		// 	message: '该账号暂无权限登录'
		// }
	}

	async logout(token) {
		return await uniID.logout(token)
	}

	async checkToken(token) {
		const auth = await uniID.checkToken(token, {
			needPermission: true,
			needUserInfo: false
		})
		if (auth.code) {
			// 校验失败，抛出错误信息
			this.ctx.throw('TOKEN_INVALID', `${auth.message}，${auth.code}`)
		}
		this.ctx.auth = auth // 设置当前请求的 auth 对象
	}

	async hasAdmin() {
		const {
			total
		} = await this.db.collection('uni-id-users').where({
			role: 'admin'
		}).count()

		return !!total
	}

	async getCurrentUserInfo(field = []) {
		return uniID.getUserInfo({
			uid: this.ctx.auth.uid,
			field
		})
	}

	async getAccount() {
		try {
			let userInfo = await dbHelper.getById("uni-id-users", this.ctx.auth.uid)
			let account = await dbHelper.getOne("t3ds-account", {
				userId: userInfo._id
			})
			return {
				code: 200,
				result: account
			}
		} catch (e) {
			return {
				code: 500,
				result: e.message
			}
		}
	}

	async applyWithdraw(fee, password) {
		let transaction
		try {
			let user = await dbHelper.getById("uni-id-users", this.ctx.auth.uid)
			if (user.role.some(role => {
					return role !== 'member'
				})) {
				if (!password) {
					return {
						code: 500,
						msg: '密码不能为空'
					}
				}
				const encResult = await uniID.encryptPwd(password)
				if (encResult.passwordHash !== user.password) {
					return {
						code: 500,
						msg: '密码不正确'
					}
				}
			}
			transaction = await this.db.startTransaction()
			let dbCmd = this.db.command
			let apply = await dbHelper.getOne("t3ds-withdraw-apply", {
				userId: user._id,
				status: "WAITING"
			})
			if (apply) {
				await transaction.commit()
				return {
					code: 500,
					msg: "您有未审核的提现申请，请耐心等待审核！"
				}
			}
			let isBoss = user.role.some(role => {
				return role === 'boss'
			})
			if ((!isBoss && (!user.wx_openid || !user.wx_openid["mp-weixin"])) ||
				isBoss && (!user.merchant_info || !user.merchant_info.wx_openid || !user.merchant_info
					.wx_openid["mp-weixin"])) {
				await transaction.commit()
				return {
					code: 500,
					msg: "请先绑定微信，再来提现"
				}
			}
			var account = await dbHelper.getOne("t3ds-account", {
				userId: user._id
			})
			if (!account) {
				await transaction.commit()
				return {
					code: 500,
					msg: "账户不存在，不能提现"
				}
			}
			account = await dbHelper.getById("t3ds-account", account._id, transaction)
			if (fee > account.balance) {
				await transaction.commit()
				return {
					code: 500,
					msg: "可用余额不足"
				}
			}
			// if (fee > 5000) {
			// 	await transaction.commit()
			// 	return {
			// 		code: 500,
			// 		msg: "提现最大金额为5000"
			// 	}
			// }
			if(isBoss) {
				if(user.merchant_info.pledgeFlag) {
					let sysConfig = await dbHelper.getOne("t3ds-system-config", {
						key: 'merchantPledge'
					})
					let merchantPledge = parseInt(sysConfig.value)
					if (account.balance - fee < merchantPledge) {
						await transaction.commit()
						return {
							code: 500,
							msg: "账户中需要预留保证金"
						}
					}
					let sysConfig2 = await dbHelper.getOne("t3ds-system-config", {
						key: 'maxWithdrawal'
					})
					let maxWithdrawal = parseInt(sysConfig2.value)
					if (fee > maxWithdrawal) {
						await transaction.commit()
						return {
							code: 500,
							msg: "超过最大提现金额，无法提现"
						}
					}
				}
			}
			account.balance -= fee;
			account.frozen += fee;
			await dbHelper.update("t3ds-account", account, transaction);
			apply = {
				userId: user._id,
				isMember: !isBoss,
				fee: fee,
				createTime: Date.now(),
				createBy: user.nickname || user.username,
				phone: user.mobile,
				status: "WAITING"
			}
			await dbHelper.insert("t3ds-withdraw-apply", apply, transaction);

			await transaction.commit();

			//发送通知给管理员
			try {
				var admins = await dbHelper.getList("uni-id-users", {
					role: "admin"
				})
				admins = admins.filter(item => {
					return item.merchant_info && item.merchant_info.wx_unionid != undefined
				})
				let unionIds = admins.map(item => {
					return item.merchant_info.wx_unionid
				})
				console.log("管理员unionIds", unionIds);
				if (unionIds.length) {
					let wxPubUsers = await dbHelper.getList("t3ds-wx-pub-user", {
						unionId: dbCmd.in(unionIds)
					})
					if (wxPubUsers.length) {
						let adminDic = {}
						admins.forEach(item => {
							adminDic[item.merchant_info.wx_unionid] = item
						})
						console.log("发送通知给如下openId", wxPubUsers.map(item => {
							return item.openId;
						}));
						for (var i = 0; i < wxPubUsers.length; i++) {
							let u = wxPubUsers[i];
							let temp = await dbHelper.getOne('t3ds-region', {
								'city.value': user.city
							})
							let tempId = temp.templateMsgs.find(item => {
								return item.templateName === '提现申请通知'
							}).templateID
							await wxPubApi.sendTemplateMsg(adminDic[u.unionId].city, {
								touser: u.openId,
								template_id: tempId,
								miniprogram: {
									appid: "wxa7e5444036dea6af",
									pagepath: "pages/index/index"
								},
								data: {
									first: {
										value: "有一条提现申请待处理"
									},
									keyword1: {
										value: user.nickname || user.username
									},
									keyword2: {
										value: moment().tz("Asia/Shanghai").format(
											"YYYY-MM-DD HH:mm:ss")
									},
									keyword3: {
										value: (fee / 100).toFixed(2)
									},
									keyword4: {
										value: '微信零钱'
									},
									remark: {
										value: '请及时处理'
									}
								}
							})
						}
					} else {
						console.log("没有找到任何管理员公众号用户");
					}
				} else {
					console.log("没有找到任何管理员unionId");
				}
			} catch (e) {
				console.error("发送通知遇到错误", e.message || '');
			}

			return {
				code: 200,
				result: apply
			}
		} catch (e) {
			console.log("申请提现遇到错误，事务回滚", e);
			if (transaction) {
				await transaction.rollback();
			}
			return {
				code: 500,
				msg: e.message
			}
		}
	}
}
